Add OTEL gen-ai message format support for input/output message tracing(Manual instrument)#225
Add OTEL gen-ai message format support for input/output message tracing(Manual instrument)#225
Conversation
- Add OTEL gen-ai semantic convention types (ChatMessage, OutputMessage, MessageRole, FinishReason, MessagePart discriminated union with support for text, tool calls, reasoning, blob, file, URI, and generic parts) - Add message-utils with conversion helpers and binary-search-based serialization with truncation sentinel for MAX_ATTRIBUTE_LENGTH - Move recordInputMessages/recordOutputMessages to protected base class (OpenTelemetryScope) with public overrides on InferenceScope, InvokeAgentScope, and OutputScope; ExecuteToolScope intentionally excluded - Widen method signatures to accept InputMessages/OutputMessages union (string[] auto-wrapped to OTEL format, structured objects pass through) - Update OutputResponse.messages type from string[] to OutputMessages - Update design doc, CHANGELOG, and add comprehensive test coverage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds OpenTelemetry Gen-AI semantic-convention message support to the observability SDK, enabling structured (multi-part / multi-modal) input/output message tracing with safe serialization under span attribute limits.
Changes:
- Introduces OTEL gen-ai message types (
ChatMessage,OutputMessage,MessagePart,MessageRole,FinishReason, etc.) and widens scope APIs to acceptInputMessages/OutputMessagesunions. - Adds
message-utils.tshelpers for string-to-OTEL conversion and length-capped JSON serialization with truncation sentinel. - Refactors message recording into
OpenTelemetryScope(protected) with public overrides on relevant scopes; updates tests/docs/changelog accordingly.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/observability/tracing/message-utils.test.ts | Adds unit tests for conversion helpers and serialization/truncation behavior. |
| tests/observability/extension/hosting/scope-utils.test.ts | Updates expectations to new structured OTEL input message JSON format. |
| tests/observability/extension/hosting/output-logging-middleware.test.ts | Updates output message attribute assertions to structured OTEL format. |
| tests/observability/core/scope-messages.test.ts | Adds integration-style tests verifying scope message recording for strings + structured parts. |
| tests/observability/core/output-scope.test.ts | Updates OutputScope tests for structured OTEL output messages and new unions. |
| packages/agents-a365-observability/src/tracing/scopes/OutputScope.ts | Stores accumulated output messages as OutputMessage[] and serializes via serializeMessages. |
| packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts | Adds protected recordInputMessages/recordOutputMessages using message-utils conversion + serialization. |
| packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts | Widens message-recording method signatures and delegates to base implementations. |
| packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts | Removes JSON.stringify-based message recording and delegates to base OTEL message recording. |
| packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts | No functional changes (formatting-only). |
| packages/agents-a365-observability/src/tracing/message-utils.ts | New helpers for type-guarding, conversion, and capped JSON serialization with sentinel truncation. |
| packages/agents-a365-observability/src/tracing/contracts.ts | Adds OTEL gen-ai message types and changes OutputResponse.messages to OutputMessages. |
| packages/agents-a365-observability/src/index.ts | Exports new OTEL gen-ai message types from the public package surface. |
| packages/agents-a365-observability/docs/design.md | Documents new message format, serialization, and scope visibility decisions. |
| CHANGELOG.md | Notes the breaking type change and new OTEL message format additions. |
| return '[' + serialized.slice(0, bestCount).join(',') + ',' + sentinel + ']'; | ||
| } | ||
|
|
||
| return truncateValue('[' + serialized[0] + ']'); |
There was a problem hiding this comment.
serializeMessages() falls back to truncateValue('[' + serialized[0] + ']') when even a single message can’t fit. This truncates an arbitrary JSON string, which can easily produce an invalid/non-parseable JSON array in the GEN_AI_*_MESSAGES span attributes. Consider keeping the attribute value valid JSON by truncating message part content before JSON.stringify, or by returning a valid sentinel-only array/object when a single message exceeds MAX_ATTRIBUTE_LENGTH.
| return truncateValue('[' + serialized[0] + ']'); | |
| // If even a single message cannot fit, fall back to a small, valid JSON array | |
| // containing only a sentinel message indicating full truncation. | |
| const sentinelAll = buildSentinel(total, total); | |
| return '[' + sentinelAll + ']'; |
…re-export Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
ChatMessage,OutputMessage,MessageRole,FinishReason,MessagePartdiscriminated union) with multi-modal supportmessage-utils.tswith conversion helpers and binary-search-based serialization with truncation sentinel forMAX_ATTRIBUTE_LENGTHrecordInputMessages/recordOutputMessagesto protected base class with public overrides onInferenceScope,InvokeAgentScope, andOutputScope;ExecuteToolScopeintentionally excludedInputMessages/OutputMessagesunion (string[]auto-wrapped to OTEL format)OutputResponse.messagestype fromstring[]toOutputMessages(breaking change — backward compatible at runtime)Test plan
message-utils.test.ts— 16 tests for conversion and serialization (truncation, boundaries, sentinel)scope-messages.test.ts— 9 tests for scope message recording (string/structured input/output, complex part types, recordResponse)output-scope.test.ts— 6 tests updated for new OTEL formatoutput-logging-middleware,scope-utils)Sample Spans
Captured from
basic-agent-sdk-samplevianpm start+curl POST /api/messages. ConsoleSpanExporter output (5 spans):Click to expand full console output
🤖 Generated with Claude Code